// SSE
import { $modal } from '@/plugins'
import $store from '@/store'
import utf8Array2Str from 'utf8array2str'
import { UUIDGenerator } from './UUID'

interface EventData<T> {
  messageType: number
  data: T
}

class EventSource {
  public onHeadersReceived: (fun: (res: any) => void) => void
  public onChunkReceived: (fun: (res: any) => void) => void
}

class SSEConfig {
  public path: string
  public data?: { [key: string]: any }
  public header?: { [key: string]: string }
}

// 解析行
function lineParse(line: string) {
  if (line == null || line.trim() == '') return [null, null]
  // 补丁
  if (!/^[\w]+:/.test(line) && !/^:-/.test(line)) {
    return ['data', line]
  }
  // 正常逻辑
  if (!line || !line.trim()) return [null, null]
  const [_, key, value] = line.match(/(^[^:]*)\s*:(.*)/) || []
  return [key, value]
}

// SSE返回数据解析
function parseTsData(lines = '') {
  console.log('lines:', lines)
  const data: { [key: string]: any } = {}
  lines.split('\n').forEach((line) => {
    const [key, value] = lineParse(line)
    if (key != null && value != null) {
      data[key] = data[key] ? data[key] + value : value
    }
  })
  return data
}

type SubscribeMessageHandler<T> = (args: EventData<T>) => void
type MessageHandler = (args: Subscriber) => void
class Subscriber {
  private listeners: { [key: string]: SubscribeMessageHandler<any> } = {}
  public subscribe<T>(key: string | number, subscribeMessageHandler: SubscribeMessageHandler<T>) {
    this.listeners[key + ''] = subscribeMessageHandler
    return this
  }
  public publish<T>(data: EventData<T>): void {
    const key = data.messageType + ''
    if (this.listeners[key]) {
      this.listeners[key](data)
    }
  }
}
export class SSEConnection {
  private requestTask: EventSource
  private config: SSEConfig
  private onOpenHandler: (data: any) => void
  private onFailHandler: (data: any) => void
  private onCloseHandler: () => void
  private onMessageHandler: MessageHandler
  private subscriberCore: Subscriber = new Subscriber()
  private isClosed = false // 新增标志位
  private clientId = $store.cart.clientId.getValue()

  constructor(config = new SSEConfig()) {
    this.config = config
  }

  public async start() {
    const that = this
    that.isClosed = false // 启动时重置

    async function startCore() {
      return new Promise((resolve, reject) => {
        const tier = setTimeout(async () => {
          that.config.header = {
            ...that.config.header,
            Authorization: $store.user.tokens.getValue()?.access_token || ''
          }
          // 准备SSE
          let url = `${import.meta.env.VITE_APP_BASE_API}${that.config.path}`
          // 追加 clientId 参数
          url += `${url.includes('?') ? '&' : '?'}clientId=${that.clientId}`
          console.log('SSE connecting...')
          that.requestTask = uni.request({
            url: url,
            responseType: 'arraybuffer',
            method: 'GET',
            timeout: 0,
            enableChunked: true,
            data: that.config.data,
            header: that.config.header,
            complete: (res: any) => {
              if (res.statusCode === 424) {
                that.onFailHandler(res)
                console.log('SSE connect fail !')
              } else {
                console.log('SSE connect complete !', res)
              }
              // 连接完成后向后端发送清理事件
              that.sendCleanupEvent()
              if (!that.isClosed) {
                that.onCloseHandler && that.onCloseHandler()
              }
              clearInterval(tier)
              resolve(false)
            },
            error: (err: any) => {
              console.error('SSE connect error !', err)
              // 连接错误后向后端发送清理事件
              that.sendCleanupEvent()
            }
          }) as any

          function processMessage(sseDataObj: { [string: string]: any }) {
            if (sseDataObj.event === 'open-event') {
              that.onOpenHandler && that.onOpenHandler(sseDataObj.data)
            }
            if (!sseDataObj.event) {
              // this.onMessageHandler && this.onMessageHandler({ data: sseDataObj.data, subscriber: that.subscriber })
              try {
                const result = JSON.parse(sseDataObj.data)
                that.onMessageHandler && that.onMessageHandler(result)
                that.subscriberCore.publish(result)
              } catch (error) {
                that.onMessageHandler && that.onMessageHandler(sseDataObj.data)
              }
            }
          }
          that.requestTask.onChunkReceived(async (res) => {
            const text = utf8Array2Str(new Uint8Array(res.data))
            // const text = new TextDecoder('utf-8').decode(new Uint8Array(res.data))
            // 不一定text就是一项，如果连续后端发，都会连在一个text里，所以要进行分隔开单独处理
            text.split(/\n{2,}/).forEach((text) => processMessage(parseTsData(text)))
          })
        }, 2000)
      })
    }
    // eslint-disable-next-line no-constant-condition
    while (true) {
      if (this.isClosed) break
      await startCore()
    }
  }

  // 添加发送清理事件的方法
  private sendCleanupEvent() {
    if (!this.config?.path) return

    // 拆分 path 和 query
    const [pathPart, queryPart = ''] = this.config.path.split('?')

    // 拆分路径并替换最后一个非空的段为 close
    const segments = pathPart.split('/')
    for (let i = segments.length - 1; i >= 0; i--) {
      if (segments[i].trim() !== '') {
        segments[i] = 'close'
        break
      }
    }
    const closePath = segments.join('/')

    // 解析 query 参数为对象
    const queryObj: Record<string, any> = {}
    if (queryPart) {
      queryPart.split('&').forEach((pair) => {
        const [k, v] = pair.split('=')
        if (k) queryObj[decodeURIComponent(k)] = v ? decodeURIComponent(v) : ''
      })
    }

    // 如果没有 clientId 参数且有 this.clientId，则添加
    if (!('clientId' in queryObj) && this.clientId) {
      queryObj.clientId = this.clientId
    }

    // 拼接 query 字符串
    const finalQuery = Object.keys(queryObj)
      .map((k) => `${encodeURIComponent(k)}=${encodeURIComponent(queryObj[k])}`)
      .join('&')

    // 最终 URL
    const finalPath = finalQuery ? `${closePath}?${finalQuery}` : closePath
    const baseUrl = `${import.meta.env.VITE_APP_BASE_API}${finalPath}`
    // 发送非 SSE 的清理请求
    uni.request({
      url: baseUrl,
      method: 'POST',
      data: this.config.data, // 保留 data 形式的参数（POST 体 / GET query 都会兼容）
      header: {
        ...this.config.header,
        Authorization: $store.user.tokens.getValue()?.access_token || ''
      },
      success: (res) => {
        console.log('SSE clear success !', res)
      },
      fail: (err) => {
        console.error('SSE clear failed !', err)
      }
    })
  }

  public onOpen(handler: (data: any) => void) {
    this.onOpenHandler = handler
    return this
  }
  public onFail(handler: (data: any) => void) {
    this.onFailHandler = handler
    return this
  }

  public onMessage(handler: MessageHandler) {
    this.onMessageHandler = handler
    return this
  }
  public subscriber(messageHandler: MessageHandler) {
    messageHandler(this.subscriberCore)
    return this
  }

  public onClose(handler: () => void) {
    this.onCloseHandler = handler
    return this
  }

  // 手动关闭方法
  public close() {
    this.isClosed = true
    if (this.requestTask && typeof (this.requestTask as any).abort === 'function') {
      ;(this.requestTask as any).abort()
    }
    this.onCloseHandler && this.onCloseHandler()
  }
}
